/* $Header: beep.c,v 2.2 01/10/02 10:26:16 przybyls Exp $ */

/***********************************************************************
 * Module:  beep.c - functions to operate the IQ beeper
 *
 * Author: John DeGood/HP Little Falls Site
 *
 * Copyright (c) 1992 by Hewlett-Packard Co.
 **********************************************************************/

#include <typedefs.h>
#include <stdarg.h>
#include <i_op.h>
#include <iomap.h>
#include <beep.h>

#define MAX_TONES       7       /* max # of tones in one call to BeepBeep() */
#define TASK_MSEC       20      /* approx # of msec between calls to this task */

/*--------begin change by wangwei----------*/
#define BEEP_OFF        printf("BEEP_OFF\n");
//#define BEEP_OFF        INTERRUPTS_OFF \
//                        BEEP_OUT = BEEP_OFF_MASK; \
//                        INTERRUPTS_ON
/*--------end change----------------------*/
typedef struct
{
        U_INT8 regA;            /* RTC RegA value for this freq */
        U_INT16 onTime;         /* msec */
        U_INT16 offTime;        /* msec */
} BEEP_TONE;

static struct
{
        U_INT8 priority;                /* 0 is lowest, 255 is highest */
        U_INT8 maxCycles;
        U_INT8 currentCycles;
        U_INT16 maxPeriod;              /* msec */
        U_INT16 currentPeriod;          /* msec */
        BEEP_TONE tone[MAX_TONES];
} Beeper;

/*********************/
/* STATIC PROTOTYPES */
/*********************/

static U_INT8 RegA(U_INT16 freq);
static void OutputBeep(void);

/*************/
/* FUNCTIONS */
/*************/

/* RegA - return 0 for 512, 1 for 1KHz                                  */
static U_INT8 RegA(U_INT16 freq)
{
        /* NOTE: Vireo only has 512 & 1K tones.  Lower = 512, higher = 1K      */

   if (freq <= 512)
   {
      return BEEP_512_MASK;
   }
   else
   {
      return BEEP_1KHZ_MASK;
   }
}

/* OutputBeep - set the hardware to the appropriate state within a beep */
static void OutputBeep(void)
{
/*--------begin change by wangwei----------*/
  printf("call OutputBeep\n");

//        INT32 i;
//
//        /* linear search for active beep - this is not efficient,
//           but the array is short */
//        for (i = 0; i < MAX_TONES; i++)
//        {
//               if (Beeper.currentPeriod >= Beeper.tone[i].onTime &&
//                    Beeper.currentPeriod <= Beeper.tone[i].offTime)
//                {
//                        /* this tone is active */
//                        INTERRUPTS_OFF
//
//                        /* set frequency */
//                        /* set tone on */
//                        BEEP_OUT = BEEP_ON_MASK | Beeper.tone[i].regA;
//
//                        INTERRUPTS_ON
//
//                        /* un-structured exit */
//                        return;
//                }
//        }

//        /* set tone off if no tone is active */
//        BEEP_OFF
/*--------end change----------------------*/
}

/* BeepBeep - control the IQ beeper
 *
 * parameters:
 *      - U_INT8 priority (0 = lowest, 255 = highest)
 *      - U_INT16 period (duration of one cycle in millisec)
 *      - U_INT8 cycles (number of times cycle is repeated; 0 = continuous)
 *      - U_INT32 tonesPerCycle (number of tone definitions for one cycle)
 *
 * tone definitions follow as the end of the parameter list;
 *      - U_INT32 freq (Hz)
 *      - U_INT32 onTime (millisec from beginning of cycle)
 *      - U_INT32 offTime (millisec from beginning of cycle)
 *
 * If (priority >= active_priority) then a new beep will replace an active beep.
 *
 * To silence beeper, use IQ_Beep(255,0,x,x).
 *
 * Current IQ implementation limitations:
 *      - Frequency is rounded to nearest IQ hardware frequency
 *        (8192, 4096, 2048, 1024, 512, ...);
 *      - Period, onTime, and offTime are internally controlled with
 *        approximately 19.5 msec resolution.
 */

void BeepBeep(U_INT8 priority,
              U_INT16 period,
              U_INT8 cycles,
              U_INT32 tonesPerCycle,
              ...)
{
        va_list ap;
        INT32 i;
printf("call BeepBeep\n");
return;
        va_start(ap, tonesPerCycle);

        INTERRUPTS_OFF

        /* if another beep is active, execute only if (priority >= active_priority) */
        if (Beeper.maxPeriod == 0 || priority >= Beeper.priority)
        {
                /* fill in the Beeper data structure */
                Beeper.priority = priority;
                Beeper.maxPeriod = period;
                Beeper.currentPeriod = 0;
                Beeper.maxCycles = cycles;
                Beeper.currentCycles = 0;

                /* set the tones specified in the parameter list */
                for (i = 0; (U_INT32)i < tonesPerCycle; i++)
                {
                        Beeper.tone[i].regA = RegA(va_arg(ap, U_INT32));
                        Beeper.tone[i].onTime = (U_INT16)va_arg(ap, U_INT32);
                        Beeper.tone[i].offTime = (U_INT16)va_arg(ap, U_INT32);
                }

                /* clear any unspecified tones */
                for (; (U_INT32)i < MAX_TONES; i++)
                {
                        Beeper.tone[i].onTime = 0xffff;
                        Beeper.tone[i].offTime = 0;
                }
        }

        INTERRUPTS_ON

        va_end(ap);
}

/* HandleBeep - audio beeper task, called by ZoneTask() at 51.2 Hz rate */
void HandleBeep(void)
{
        /* is there a beep to process? */
        if (Beeper.maxPeriod > 0)
        {
                /* have we completed this cycle? */
                if (Beeper.currentPeriod >= Beeper.maxPeriod)
                {
                        /* increment cycle count */
                        Beeper.currentCycles++;

                        /* is there another cycle required? */
                        if (Beeper.currentCycles < Beeper.maxCycles || Beeper.maxCycles == 0)
                        {
                                /* start new cycle */
                                Beeper.currentPeriod = 0;
                        }
                        else
                        {
                                /* this was the last cycle */
                                /* reset beep data structure */
                                Beeper.maxPeriod = 0;

                                /* set tone off */
                                BEEP_OFF

                                /* unstructured exit */
                                return;
                        }
                }

                /* set tone to correct state */
                OutputBeep();

                /* increment period time count */
                Beeper.currentPeriod += TASK_MSEC;
        }
        else
        {
                /* set tone off -  do this repeatedly for ESD resistance */
                BEEP_OFF
        }
}
